package com.xcf.mybatis_example.service;

import com.xcf.mybatis_example.dao.mapper.UserMapper;
import com.xcf.mybatis_example.dao.mapper.UserRoleDataMapper;
import com.xcf.mybatis_example.dao.pojo.User;
import com.xcf.mybatis_example.dao.pojo.UserRoleData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    private final Lock lock = new ReentrantLock( );

    @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
    public void update(User user) {
        User top = userMapper.findTopByUsername(user);
        if (null == top) {
            System.out.println("Lock 之前 = " + Thread.currentThread( ).getName( ));
            /*lock.lock( );
            System.out.println("Lock 进入 = " + Thread.currentThread( ).getName( ));
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter( ) {
                @Override
                public void afterCompletion(int status) {
                    super.afterCompletion(status);
                    System.out.println("==== afterCompletion = " + Thread.currentThread( ).getName( ));
                    lock.unlock( );
                }
            });*/
            synchronized (lock) {
                top = userMapper.findCCTopByUsername(user);
                System.out.println("second top = " + top);
                if (null == top) {
                    top = new User( );
                    top.setUsername(user.getUsername( ))
                            .setNum(user.getNum( ))
                            .setUpdate_time(new Date( ))
                    ;
                    userMapper.save(top);
                    return;
                }
            }
        }
        userMapper.update(user);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
    public synchronized void update4(User user) {
        User top = userMapper.findCCTopByUsername(user);
        System.out.println("second top = " + top);
        if (null == top) {
            top = new User( );
            top.setUsername(user.getUsername( ))
                    .setNum(user.getNum( ))
                    .setUpdate_time(new Date( ))
            ;
            userMapper.save(top);
        } else {

            userMapper.update(user);
        }
    }

    @Autowired
    private UserRoleDataMapper userRoleDataMapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
    public synchronized void updateData(User user) {
        UserRoleData top = userRoleDataMapper.select();
        System.out.println("second top = " + top);
        if (null == top) {
            userRoleDataMapper.save();
        } else {
            userRoleDataMapper.update();
        }
    }

    //    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void update2(User user) {
        User top = userMapper.findTopByUsername(user);
        if (null == top) {
            synchronized (lock) {
                top = userMapper.findTopByUsername(user);
                if (null == top) {
                    top = new User( );
                    top.setUsername(user.getUsername( ))
                            .setNum(user.getNum( ))
                    ;
                    userMapper.save(top);
                    return;
                }
            }
        }
        userMapper.update(user);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
    public void update3(User user) {
        String username = user.getUsername( );
        User old = userMapper.findTopByUsername(user);
        if (null != old) {
            userMapper.update(user);
        } else {
            synchronized (username) {
                old = userMapper.findTopByUsername(user);
                if (null != old) {
                    userMapper.update(user);
                } else {
                    userMapper.save(user);
                }
            }
        }

    }
}
